Commit c94fbb2b authored by Rob Swindell's avatar Rob Swindell 💬
Browse files

Add JS methods for vetting filenames (e.g. for upload by users)

system.illegal_filename() - check if contains illegal chars/sequences
system.safest_filename() - check if contains only safest chars
system.allowed_filename() - check if meets criteria from SCFG->File Options
system.check_filename() - check if legal and meets configured criteria and is not in file.can
bbs.check_filename() - ditto, except will display badfile.msg as appropriate

Now scripts can utilize the sysop-controlled filename criteria and security of the BBS.
parent bc424632
Pipeline #2597 passed with stage
in 9 minutes and 24 seconds
......@@ -1387,6 +1387,34 @@ js_user_event(JSContext *cx, uintN argc, jsval *arglist)
return(JS_TRUE);
}
static JSBool
js_checkfname(JSContext *cx, uintN argc, jsval *arglist)
{
jsval *argv = JS_ARGV(cx, arglist);
sbbs_t* sbbs;
char* fname = NULL;
jsrefcount rc;
JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
if(argc < 1 || !JSVAL_IS_STRING(argv[0]))
return JS_TRUE;
if((sbbs = js_GetPrivate(cx, JS_THIS_OBJECT(cx, arglist))) == NULL)
return JS_FALSE;
JSVALUE_TO_MSTRING(cx, argv[0], fname, NULL);
if(fname == NULL)
return JS_FALSE;
rc=JS_SUSPENDREQUEST(cx);
JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(sbbs->checkfname(fname)));
JS_RESUMEREQUEST(cx, rc);
free(fname);
return JS_TRUE;
}
static JSBool
js_chksyspass(JSContext *cx, uintN argc, jsval *arglist)
{
......@@ -4632,6 +4660,12 @@ static jsSyncMethodSpec js_bbs_functions[] = {
,316
},
/* security */
{"check_filename", js_checkfname, 1, JSTYPE_BOOLEAN, JSDOCSTR("filename")
,JSDOCSTR("verify that the specified <i>filename</i> string is legal and allowed for upload "
"(based on system configuration), returns <i>true</i> if the filename is allowed.<br>"
"Note: Will display <tt>text/badfile.msg</tt> for matching filenames, if it exists.")
,31902
},
{"check_syspass", js_chksyspass, 0, JSTYPE_BOOLEAN, JSDOCSTR("[sys_pw]")
,JSDOCSTR("verify system password, prompting for the password if not passed as an argument")
,310
......
......@@ -1924,6 +1924,117 @@ js_chkname(JSContext *cx, uintN argc, jsval *arglist)
return(JS_TRUE);
}
static JSBool
js_chkfname(JSContext *cx, uintN argc, jsval *arglist)
{
JSObject *obj = JS_THIS_OBJECT(cx, arglist);
jsval *argv = JS_ARGV(cx, arglist);
char* fname = NULL;
jsrefcount rc;
JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
if(argc < 1 || !JSVAL_IS_STRING(argv[0]))
return JS_TRUE;
js_system_private_t* sys;
if((sys = (js_system_private_t*)js_GetClassPrivate(cx,obj,&js_system_class))==NULL)
return JS_FALSE;
JSVALUE_TO_MSTRING(cx, argv[0], fname, NULL);
if(fname == NULL)
return JS_FALSE;
rc=JS_SUSPENDREQUEST(cx);
JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(!illegal_filename(fname)
&& allowed_filename(sys->cfg, fname)
&& !trashcan(sys->cfg, fname, "file")));
JS_RESUMEREQUEST(cx, rc);
free(fname);
return JS_TRUE;
}
static JSBool
js_safest_fname(JSContext *cx, uintN argc, jsval *arglist)
{
JSObject *obj = JS_THIS_OBJECT(cx, arglist);
jsval *argv = JS_ARGV(cx, arglist);
char* fname = NULL;
jsrefcount rc;
JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
if(argc < 1 || !JSVAL_IS_STRING(argv[0]))
return JS_TRUE;
JSVALUE_TO_MSTRING(cx, argv[0], fname, NULL);
if(fname == NULL)
return JS_FALSE;
rc=JS_SUSPENDREQUEST(cx);
JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(safest_filename(fname)));
JS_RESUMEREQUEST(cx, rc);
free(fname);
return JS_TRUE;
}
static JSBool
js_illegal_fname(JSContext *cx, uintN argc, jsval *arglist)
{
JSObject *obj = JS_THIS_OBJECT(cx, arglist);
jsval *argv = JS_ARGV(cx, arglist);
char* fname = NULL;
jsrefcount rc;
JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
if(argc < 1 || !JSVAL_IS_STRING(argv[0]))
return JS_TRUE;
JSVALUE_TO_MSTRING(cx, argv[0], fname, NULL);
if(fname == NULL)
return JS_FALSE;
rc=JS_SUSPENDREQUEST(cx);
JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(illegal_filename(fname)));
JS_RESUMEREQUEST(cx, rc);
free(fname);
return JS_TRUE;
}
static JSBool
js_allowed_fname(JSContext *cx, uintN argc, jsval *arglist)
{
JSObject *obj = JS_THIS_OBJECT(cx, arglist);
jsval *argv = JS_ARGV(cx, arglist);
char* fname = NULL;
jsrefcount rc;
JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
if(argc < 1 || !JSVAL_IS_STRING(argv[0]))
return JS_TRUE;
js_system_private_t* sys;
if((sys = (js_system_private_t*)js_GetClassPrivate(cx,obj,&js_system_class))==NULL)
return JS_FALSE;
JSVALUE_TO_MSTRING(cx, argv[0], fname, NULL);
if(fname == NULL)
return JS_FALSE;
rc=JS_SUSPENDREQUEST(cx);
JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(allowed_filename(sys->cfg, fname)));
JS_RESUMEREQUEST(cx, rc);
free(fname);
return JS_TRUE;
}
#endif
static JSBool
......@@ -2128,6 +2239,25 @@ static jsSyncMethodSpec js_system_functions[] = {
"returns <i>true</i> if it is valid")
,315
},
{"check_filename", js_chkfname, 1, JSTYPE_BOOLEAN, JSDOCSTR("filename")
,JSDOCSTR("verify that the specified <i>filename</i> string is legal and allowed for upload by users "
"(based on system configuration), returns <i>true</i> if the filename is allowed")
,31902
},
{"allowed_filename", js_allowed_fname, 1, JSTYPE_BOOLEAN, JSDOCSTR("filename")
,JSDOCSTR("verify that the specified <i>filename</i> string is allowed for upload by users "
"(based on system configuration), returns <i>true</i> if the filename is allowed")
,31902
},
{"safest_filename", js_safest_fname, 1, JSTYPE_BOOLEAN, JSDOCSTR("filename")
,JSDOCSTR("verify that the specified <i>filename</i> string contains only the safest subset of characters")
,31902
},
{"illegal_filename", js_illegal_fname, 1, JSTYPE_BOOLEAN, JSDOCSTR("filename")
,JSDOCSTR("check if the specified <i>filename</i> string contains illegal characters or sequences, "
"returns <i>true</i> if it is an illegal filename")
,31902
},
#endif
{"check_pid", js_chkpid, 1, JSTYPE_BOOLEAN, JSDOCSTR("process-ID")
,JSDOCSTR("checks that the provided process ID is a valid executing process on the system, "
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment