void mg_ssl_if_conn_free(struct mg_connection *nc) { struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data; if (ctx == NULL) return; nc->ssl_if_data = NULL; MG_FREE(ctx->ssl_cert); MG_FREE(ctx->ssl_key); MG_FREE(ctx->ssl_ca_cert); MG_FREE(ctx->ssl_server_name); memset(ctx, 0, sizeof(*ctx)); MG_FREE(ctx); }
static void mg_handle_tcp_read(struct mg_connection *conn) { int n = 0; char *buf = (char *) MG_MALLOC(MG_TCP_RECV_BUFFER_SIZE); if (buf == NULL) { DBG(("OOM")); return; } #if MG_ENABLE_SSL if (conn->flags & MG_F_SSL) { if (conn->flags & MG_F_SSL_HANDSHAKE_DONE) { /* SSL library may have more bytes ready to read than we ask to read. * Therefore, read in a loop until we read everything. Without the loop, * we skip to the next select() cycle which can just timeout. */ while ((n = mg_ssl_if_read(conn, buf, MG_TCP_RECV_BUFFER_SIZE)) > 0) { DBG(("%p %d bytes <- %d (SSL)", conn, n, conn->sock)); mg_if_recv_tcp_cb(conn, buf, n, 1 /* own */); buf = NULL; if (conn->flags & MG_F_CLOSE_IMMEDIATELY) break; /* buf has been freed, we need a new one. */ buf = (char *) MG_MALLOC(MG_TCP_RECV_BUFFER_SIZE); if (buf == NULL) break; } MG_FREE(buf); if (n < 0 && n != MG_SSL_WANT_READ) conn->flags |= MG_F_CLOSE_IMMEDIATELY; } else { MG_FREE(buf); mg_ssl_begin(conn); return; } } else #endif { n = (int) MG_RECV_FUNC(conn->sock, buf, recv_avail_size(conn, MG_TCP_RECV_BUFFER_SIZE), 0); DBG(("%p %d bytes (PLAIN) <- %d", conn, n, conn->sock)); if (n > 0) { mg_if_recv_tcp_cb(conn, buf, n, 1 /* own */); } else { MG_FREE(buf); } if (n == 0) { /* Orderly shutdown of the socket, try flushing output. */ conn->flags |= MG_F_SEND_AND_CLOSE; } else if (n < 0 && mg_is_error()) { conn->flags |= MG_F_CLOSE_IMMEDIATELY; } } }
/* If the file's extension is .pem, convert it to DER format and put on SLFS. */ static char *sl_pem2der(const char *pem_file) { const char *pem_ext = strstr(pem_file, ".pem"); if (pem_ext == NULL || *(pem_ext + 4) != '\0') { return strdup(pem_file); } char *der_file = NULL; /* DER file must be located on SLFS, add prefix. */ int l = mg_asprintf(&der_file, 0, MG_SSL_IF_SIMPLELINK_SLFS_PREFIX "%.*s.der", (int) (pem_ext - pem_file), pem_file); if (der_file == NULL) return NULL; bool result = false; cs_stat_t st; if (mg_stat(der_file, &st) != 0) { result = pem_to_der(pem_file, der_file); LOG(LL_DEBUG, ("%s -> %s = %d", pem_file, der_file, result)); } else { /* File exists, assume it's already been converted. */ result = true; } if (result) { /* Strip the SL: prefix we added since NWP does not expect it. */ memmove(der_file, der_file + MG_SSL_IF_SIMPLELINK_SLFS_PREFIX_LEN, l - 2 /* including \0 */); } else { MG_FREE(der_file); der_file = NULL; } return der_file; }
void mg_lwip_ssl_recv(struct mg_connection *nc) { struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; /* Don't deliver data before connect callback */ if (nc->flags & MG_F_CONNECTING) return; while (nc->recv_mbuf.len < MG_LWIP_SSL_RECV_MBUF_LIMIT) { char *buf = (char *) MG_MALLOC(MG_LWIP_SSL_IO_SIZE); if (buf == NULL) return; int ret = mg_ssl_if_read(nc, buf, MG_LWIP_SSL_IO_SIZE); DBG(("%p %p SSL_read %u = %d", nc, cs->rx_chain, MG_LWIP_SSL_IO_SIZE, ret)); if (ret <= 0) { MG_FREE(buf); if (ret == MG_SSL_WANT_WRITE) { nc->flags |= MG_F_WANT_WRITE; return; } else if (ret == MG_SSL_WANT_READ) { /* * Nothing to do in particular, we are callback-driven. * What we definitely do not need anymore is SSL reading (nothing left). */ nc->flags &= ~MG_F_WANT_READ; cs->err = 0; return; } else { mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc); return; } } else { mg_if_recv_tcp_cb(nc, buf, ret, 1 /* own */); } } }
int fs_slfs_open(const char *pathname, int flags, mode_t mode) { int fd; for (fd = 0; fd < MAX_OPEN_SLFS_FILES; fd++) { if (s_sl_fds[fd].fh <= 0) break; } if (fd >= MAX_OPEN_SLFS_FILES) return set_errno(ENOMEM); struct sl_fd_info *fi = &s_sl_fds[fd]; /* * Apply path manipulations again, in case we got here directly * (via TI libc's "add_device"). */ pathname = drop_dir(pathname, NULL); _u32 am = 0; fi->size = (size_t) -1; int rw = (flags & 3); size_t new_size = FS_SLFS_MAX_FILE_SIZE; if (rw == O_RDONLY) { SlFsFileInfo_t sl_fi; _i32 r = sl_FsGetInfo((const _u8 *) pathname, 0, &sl_fi); if (r == SL_FS_OK) { fi->size = SL_FI_FILE_SIZE(sl_fi); } am = SL_FS_READ; } else { if (!(flags & O_TRUNC) || (flags & O_APPEND)) { // FailFS files cannot be opened for append and will be truncated // when opened for write. return set_errno(ENOTSUP); } if (flags & O_CREAT) { size_t i; for (i = 0; i < MAX_OPEN_SLFS_FILES; i++) { if (s_sl_file_size_hints[i].name != NULL && strcmp(s_sl_file_size_hints[i].name, pathname) == 0) { new_size = s_sl_file_size_hints[i].size; MG_FREE(s_sl_file_size_hints[i].name); s_sl_file_size_hints[i].name = NULL; break; } } am = FS_MODE_OPEN_CREATE(new_size, 0); } else { am = SL_FS_WRITE; } } fi->fh = slfs_open((_u8 *) pathname, am); LOG(LL_DEBUG, ("sl_FsOpen(%s, 0x%x) sz %u = %d", pathname, (int) am, (unsigned int) new_size, (int) fi->fh)); int r; if (fi->fh >= 0) { fi->pos = 0; r = fd; } else { r = set_errno(sl_fs_to_errno(fi->fh)); } return r; }
int closedir(DIR *dir) { int result = 0; if (dir != NULL) { if (dir->handle != INVALID_HANDLE_VALUE) result = FindClose(dir->handle) ? 0 : -1; MG_FREE(dir); } else { result = -1; SetLastError(ERROR_BAD_ARGUMENTS); } return result; }
static int mg_recvfrom(struct mg_connection *nc, union socket_address *sa, socklen_t *sa_len, char **buf) { int n; *buf = (char *) MG_MALLOC(MG_UDP_RECV_BUFFER_SIZE); if (*buf == NULL) { DBG(("Out of memory")); return -ENOMEM; } n = recvfrom(nc->sock, *buf, MG_UDP_RECV_BUFFER_SIZE, 0, &sa->sa, sa_len); if (n <= 0) { DBG(("%p recvfrom: %s", nc, strerror(mg_get_errno()))); MG_FREE(*buf); } return n; }
void mg_printf_websocket_frame(struct mg_connection *nc, int op, const char *fmt, ...) { char mem[MG_VPRINTF_BUFFER_SIZE], *buf = mem; va_list ap; int len; va_start(ap, fmt); if ((len = mg_avprintf(&buf, sizeof(mem), fmt, ap)) > 0) { mg_send_websocket_frame(nc, op, buf, len); } va_end(ap); if (buf != mem && buf != NULL) { MG_FREE(buf); } }
DIR *opendir(const char *name) { DIR *dir = NULL; wchar_t wpath[MAX_PATH]; DWORD attrs; if (name == NULL) { SetLastError(ERROR_BAD_ARGUMENTS); } else if ((dir = (DIR *) MG_MALLOC(sizeof(*dir))) == NULL) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); } else { to_wchar(name, wpath, ARRAY_SIZE(wpath)); attrs = GetFileAttributesW(wpath); if (attrs != 0xFFFFFFFF && (attrs & FILE_ATTRIBUTE_DIRECTORY)) { (void) wcscat(wpath, L"\\*"); dir->handle = FindFirstFileW(wpath, &dir->info); dir->result.d_name[0] = '\0'; } else { MG_FREE(dir); dir = NULL; } } return dir; }
int sl_set_ssl_opts(int sock, struct mg_connection *nc) { int err; const struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data; DBG(("%p ssl ctx: %p", nc, ctx)); if (ctx == NULL) return 0; DBG(("%p %s,%s,%s,%s", nc, (ctx->ssl_cert ? ctx->ssl_cert : "-"), (ctx->ssl_key ? ctx->ssl_cert : "-"), (ctx->ssl_ca_cert ? ctx->ssl_ca_cert : "-"), (ctx->ssl_server_name ? ctx->ssl_server_name : "-"))); if (ctx->ssl_cert != NULL && ctx->ssl_key != NULL) { char *ssl_cert = sl_pem2der(ctx->ssl_cert), *ssl_key = NULL; if (ssl_cert != NULL) { err = sl_SetSockOpt(sock, SL_SOL_SOCKET, SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME, ssl_cert, strlen(ssl_cert)); MG_FREE(ssl_cert); LOG(LL_DEBUG, ("CERTIFICATE_FILE_NAME %s -> %d", ssl_cert, err)); ssl_key = sl_pem2der(ctx->ssl_key); if (ssl_key != NULL) { err = sl_SetSockOpt(sock, SL_SOL_SOCKET, SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME, ssl_key, strlen(ssl_key)); MG_FREE(ssl_key); LOG(LL_DEBUG, ("PRIVATE_KEY_FILE_NAME %s -> %d", ssl_key, err)); } else { err = -1; } } else { err = -1; } if (err != 0) return err; } if (ctx->ssl_ca_cert != NULL) { if (ctx->ssl_ca_cert[0] != '\0') { char *ssl_ca_cert = sl_pem2der(ctx->ssl_ca_cert); if (ssl_ca_cert != NULL) { err = sl_SetSockOpt(sock, SL_SOL_SOCKET, SL_SO_SECURE_FILES_CA_FILE_NAME, ssl_ca_cert, strlen(ssl_ca_cert)); LOG(LL_DEBUG, ("CA_FILE_NAME %s -> %d", ssl_ca_cert, err)); } else { err = -1; } MG_FREE(ssl_ca_cert); if (err != 0) return err; } } if (ctx->ssl_server_name != NULL) { err = sl_SetSockOpt(sock, SL_SOL_SOCKET, SL_SO_SECURE_DOMAIN_NAME_VERIFICATION, ctx->ssl_server_name, strlen(ctx->ssl_server_name)); DBG(("DOMAIN_NAME_VERIFICATION %s -> %d", ctx->ssl_server_name, err)); /* Domain name verificationw as added in a NWP service pack, older * versions return SL_ERROR_BSD_ENOPROTOOPT. There isn't much we can do * about it, * so we ignore the error. */ if (err != 0 && err != SL_ERROR_BSD_ENOPROTOOPT) return err; } return 0; }
void mg_lwip_if_free(struct mg_iface *iface) { MG_FREE(iface->data); iface->data = NULL; }