]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
api: return EPERM for the empty arguments, fixes #5755
authorJaroslav Kysela <perex@perex.cz>
Mon, 21 Oct 2019 16:31:41 +0000 (18:31 +0200)
committerJaroslav Kysela <perex@perex.cz>
Mon, 21 Oct 2019 16:31:41 +0000 (18:31 +0200)
src/access.h
src/api.c
src/api.h
src/api/api_idnode.c
src/http.c

index 4539a464510e9ba1fc74f8984da5670c813da65e..4035d25846d62f2995e24efa83d64d4939c79dcd 100644 (file)
@@ -227,6 +227,7 @@ typedef struct access_ticket {
 #define ACCESS_FAILED_RECORDER    (1<<9)
 #define ACCESS_HTSP_ANONYMIZE     (1<<10)
 #define ACCESS_ADMIN              (1<<11)
+#define ACCESS_NO_EMPTY_ARGS      (1<<29)
 #define ACCESS_OR                 (1<<30)
 
 #define ACCESS_FULL \
@@ -236,6 +237,9 @@ typedef struct access_ticket {
    ACCESS_ALL_RECORDER | ACCESS_ALL_RW_RECORDER | \
    ACCESS_FAILED_RECORDER | ACCESS_ADMIN)
 
+#define ACCESS_INTERNAL \
+  (ACCESS_NO_EMPTY_ARGS)
+
 /**
  * Create a new ticket for the requested resource and generate a id for it
  */
index 868d4815678eeb1b54ba3aca702109cc1f5dcbda..b224a30c5786f46a8e4473b9d77610066447b199 100644 (file)
--- a/src/api.c
+++ b/src/api.c
@@ -67,6 +67,7 @@ api_exec ( access_t *perm, const char *subsystem,
   api_hook_t h;
   api_link_t *ah, skel;
   const char *op;
+  uint32_t access;
 
   /* Args and response must be set */
   if (!args || !resp || !subsystem)
@@ -84,7 +85,11 @@ api_exec ( access_t *perm, const char *subsystem,
     return ENOSYS; // TODO: is this really the right error code?
   }
 
-  if (access_verify2(perm, ah->hook->ah_access))
+  access = ah->hook->ah_access;
+  if ((access & ACCESS_NO_EMPTY_ARGS) != 0 && htsmsg_is_empty(args))
+    return EPERM;
+
+  if (access_verify2(perm, access & ~ACCESS_INTERNAL))
     return EPERM;
 
   /* Extract method */
index 7815e961736c77b711d446373bcc38763faa06a1..a412776b957bcc469027dba064e8d6b6808f8326 100644 (file)
--- a/src/api.h
+++ b/src/api.h
@@ -38,7 +38,7 @@ typedef int (*api_callback_t)
 typedef struct api_hook
 {
   const char         *ah_subsystem;
-  int                 ah_access;
+  uint32_t            ah_access;
   api_callback_t      ah_callback;
   void               *ah_opaque;
 } api_hook_t;
index fe0bf40a61fc774dace03118b9b701e6add0a00a..9096bfe9d82442a177a858369eaa8cf29e1da8f1 100644 (file)
@@ -741,19 +741,21 @@ api_idnode_create_list( htsmsg_t **resp, htsmsg_t *list )
   htsmsg_add_msg(*resp, "uuid", list);
 }
 
+#define ACCESS_IDNODE (ACCESS_ANONYMOUS | ACCESS_NO_EMPTY_ARGS)
+
 void api_idnode_init ( void )
 {
   /*
    * note: permissions are verified using idnode_perm() calls
    */
   static api_hook_t ah[] = {
-    { "idnode/load",     ACCESS_ANONYMOUS, api_idnode_load,     NULL },
-    { "idnode/save",     ACCESS_ANONYMOUS, api_idnode_save,     NULL },
-    { "idnode/tree",     ACCESS_ANONYMOUS, api_idnode_tree,     NULL },
-    { "idnode/class",    ACCESS_ANONYMOUS, api_idnode_class,    NULL },
-    { "idnode/delete",   ACCESS_ANONYMOUS, api_idnode_delete,   NULL },
-    { "idnode/moveup",   ACCESS_ANONYMOUS, api_idnode_moveup,   NULL },
-    { "idnode/movedown", ACCESS_ANONYMOUS, api_idnode_movedown, NULL },
+    { "idnode/load",     ACCESS_IDNODE, api_idnode_load,     NULL },
+    { "idnode/save",     ACCESS_IDNODE, api_idnode_save,     NULL },
+    { "idnode/tree",     ACCESS_IDNODE, api_idnode_tree,     NULL },
+    { "idnode/class",    ACCESS_IDNODE, api_idnode_class,    NULL },
+    { "idnode/delete",   ACCESS_IDNODE, api_idnode_delete,   NULL },
+    { "idnode/moveup",   ACCESS_IDNODE, api_idnode_moveup,   NULL },
+    { "idnode/movedown", ACCESS_IDNODE, api_idnode_movedown, NULL },
     { NULL },
   };
 
index 698167f46c014a4e3c81f4fcf3b72a029634ae10..daabbccf0a2bab876f62b5c83adf450b3ca72f81 100644 (file)
@@ -1227,7 +1227,12 @@ http_exec(http_connection_t *hc, http_path_t *hp, char *remain)
 {
   int err;
 
-  if (http_access_verify(hc, hp->hp_accessmask)) {
+  /* this is a special case when client probably requires authentication */
+  if ((hp->hp_accessmask & ACCESS_NO_EMPTY_ARGS) != 0 && TAILQ_EMPTY(&hc->hc_req_args)) {
+    err = http_noaccess_code(hc);
+    goto destroy;
+  }
+  if (http_access_verify(hc, hp->hp_accessmask & ~ACCESS_INTERNAL)) {
     if ((hp->hp_flags & HTTP_PATH_NO_VERIFICATION) == 0) {
       err = http_noaccess_code(hc);
       goto destroy;