Beispiel #1
0
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);
}
Beispiel #2
0
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;
    }
  }
}
Beispiel #3
0
/* 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;
}
Beispiel #4
0
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 */);
    }
  }
}
Beispiel #5
0
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;
}
Beispiel #6
0
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;
}
Beispiel #7
0
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;
}
Beispiel #8
0
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);
  }
}
Beispiel #9
0
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;
}
Beispiel #10
0
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;
}
Beispiel #11
0
void mg_lwip_if_free(struct mg_iface *iface) {
  MG_FREE(iface->data);
  iface->data = NULL;
}