What's new

Generate config file on router from WebUI page

  • SNBForums Code of Conduct

    SNBForums is a community for everyone, no matter what their level of experience.

    Please be tolerant and patient of others, especially newcomers. We are all here to share and learn!

    The rules are simple: Be patient, be nice, be helpful or be gone!

FreshJR

Very Senior Member
I have been poking around if there would be anyway to generate a file on the router from input on a page appended into the WebUI.

Eg. I would like to create functionality so a user can add/delete/modify QoS rules within the WebUI.
Rules can be generated within a table and upon hitting submit a file would be generated. This generated file would be parsed by the QoS script which would apply the WebUI generated rules.​

The answer I have come up with is no. The router is very locked down for security reasons.

1) upload.cgi / jffsupload.cgi /upload_cert_key.cgi /all the other relevent file *.cgi ARE able create files on the router locally from the WebUI.

The issue is that I cannot extend their functionality to create a custom file of my choosing. The file generation functionality is very sanitized and hardcoded within "release/src/router/httpd/web.c"​

2) apply.cgi is able to set nvram variables
I would perfer to generate a config file instead of wasting nvram, but the same issue applies. Setting nvram variables is also very sanitized so I cannot set a custom variable from the WebUI.​

--

Is there any trick I missed?

Can local file generation from WebUI be something to consider to extend functionality in future releases? More friendly scripts can be created as a result.

Security side, the generated config can stripped of any special characters / sanitized. The only special charterers needed would be a new line and any delimiter such as a comma.
 
Last edited:
httpd itself won't let you create files. Any file that it can create is because there's specifically code to do so in web.c, for a pre-determined filename. So no, there's no way to do so - and it there were, it would be considered a security flaw that would require addressing.

The only "generic" way you might be able to do so without modifying the httpd code is by setting an nvram variable, and having a cron job checking for the presence of that nvram, and running a shell script whenever that flag is present.
 
The only "generic" way you might be able to do so without modifying the httpd code is by setting an nvram variable, and having a cron job checking for the presence of that nvram, and running a shell script whenever that flag is present.

But aren't you only able to set a fixed list of predefined nvram variables from the WebUI ??

I thought you are only able to set the nvram variables explicitly defined within apply.cgi unless I am missing something and didn't do enough poking around yet.
 
Last edited:
But aren't you only able to set a fixed list of predefined nvram variables from the WebUI ??

I haven't checked recently what happens if you try to write an nvram that is not defined in libshared. I know that it won't survive a reboot, but I haven't checked if the webui can still set it. Give it a try.
 
I haven't checked recently what happens if you try to write an nvram that is not defined in libshared. I know that it won't survive a reboot, but I haven't checked if
the webui can still set it. Give it a try.

If that was a hint, can I get another hint?? I may be looking in the wrong location, but I scoured the httpd code front to back to find an entry way and found nothing besides hijacking existing variables!!


--

I sat down today and had a closer look at the httpd code in multiple areas. I still reached the same conclusion as my original post that you can only set predefined nvram variables when attemping to do so from the WebUI.

Setting nvram variables via the WebUI happens by the apply_cgi function within httpd/web.c

The easiest way set a variable is to use this javascript code

1)
Code:
httpApi.nvramSet({
"nvram_var" : "set_value",
"action_mode": "apply",
}, null);
Note:  This the JSON parameters in this code block are ultimately passed to apply_cgi function within httpd.c

But when using the above javascript code, the "nvram_var" has to be one that is already predefined within one of the following the two structures

Code:
router_defaults
router_state_defaults

present in shared\defaults.c

So I am back at to my original conclusion that I would have to hijack an existing nvram variable so a user created jffs script can interact with a user created WebUI page.

(Yes it is also possible to use different bits of javascript code to progress further within the "action_mode" if-tree of the apply_cgi function, but those branches still only set predefined nvram variables).

--

2)

I also tried exploring the various <% ASP_CODE_NUGGETS() %> within the "struct ej_handler ej_handlers[]", but none of those code nuggets set custom nvram variables as well.

eg.

Code:
    { "nvram_get", ej_nvram_get},
    { "nvram_default_get", ej_nvram_default_get},
    { "nvram_match", ej_nvram_match},
    { "nvram_double_match", ej_nvram_double_match},
    { "nvram_show_chinese_char", ej_nvram_show_chinese_char},
    { "nvram_get_x", ej_nvram_get_x},
    { "nvram_get_f", ej_nvram_get_f},
    { "nvram_get_list_x", ej_nvram_get_list_x},
    { "nvram_get_buf_x", ej_nvram_get_buf_x},
    { "nvram_match_x", ej_nvram_match_x},
    { "nvram_double_match_x", ej_nvram_double_match_x},
    { "nvram_match_both_x", ej_nvram_match_both_x},
    { "nvram_match_list_x", ej_nvram_match_list_x},
    { "select_channel", ej_select_channel},
    { "uptime", ej_uptime},
    { "sysuptime", ej_sysuptime},
    { "nvram_dump", ej_dump},
    { "load_script", ej_load},
    { "select_list", ej_select_list},
    { "dhcpLeaseInfo", ej_dhcpLeaseInfo},
    { "dhcpLeaseMacList", ej_dhcpLeaseMacList},
    { "IP_dhcpLeaseInfo", ej_IP_dhcpLeaseInfo},
    { "qrate", ej_qos_packet},
    ...... and so on
 
Last edited:
Just add a hidden INPUT field with the desired nvram. On POST, all these fields are saved to nvram.

httpApi is a new object that allows to more dynamically interact with the web server without requiring a POST, however I found it to be hit-or-miss so far, probably because I don't fully understand how it works. Getting nvram through it works find, setting - not so much.

Code:
<input type="hidden" name="fjr_myvar" value="<% nvram_get("fjr_myvar"); %>">

You can access that variable through document.form.fjr_myvar.value in the JS code.

EDIT: just tested it on my RT-AX88U, and it didn't set it. So, it's possible that applying now only works with variables defined in shared/defaults.c, at least on HND.
 
Just add a hidden INPUT field with the desired nvram. On POST, all these fields are saved to nvram.

httpApi is a new object that allows to more dynamically interact with the web server without requiring a POST, however I found it to be hit-or-miss so far, probably because I don't fully understand how it works. Getting nvram through it works find, setting - not so much.


You do need "action_mode": "apply" when using httpApi.nvramSet({JSON},callback)
or will it exit early before attempting to do anything. I haven't had it fail on me yet.

httpApi.nvramSet({
"nvram_var" : "set_value",
"action_mode": "apply",
}, null);

But yes, the variable is cross checked against the two structs.

Code:
    if (!strcmp(action_mode, "apply")) {    // if you have action_mode : "apply" in the JSON

        struct json_object *res=NULL;
        res = json_object_new_object();   //holds bool results desired individual JSON commands

        if (!validate_apply(wp,root)) {   //validate_apply has for loop that runs through of structs default nvram_varaibles on how to parse a specific  nvram_var and it wont parse any var not in the struct
            json_object_object_add(res, "modify", json_object_new_string("0"));  // add fail result to JSON
        }
        else {  //success
            json_object_object_add(res, "modify", json_object_new_string("1")); //add pass result to JSON
        }
 
Last edited:
You do need "action_mode": "apply" when using httpApi.nvramSet({JSON},callback)
or will it exit early before attempting to do anything. I haven't had it fail on me yet.

httpApi.nvramSet({
"nvram_var" : "set_value",
"action_mode": "apply",
}, null);

I suspect my problem with setting nvrams through httpApi has to do with instantiation. I'm unable to clear vpn_client1_rip for instance, but I have no problem setting vpn_client_unit.
 

Latest threads

Sign Up For SNBForums Daily Digest

Get an update of what's new every day delivered to your mailbox. Sign up here!
Top